package com.lindroy.androidplayer.logic.network.datasource.pagingsource

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.elvishew.xlog.XLog
import com.lindroy.androidplayer.logic.model.*
import com.lindroy.androidplayer.logic.network.base.http.EmptyDataException
import com.lindroy.androidplayer.logic.network.base.http.RequestException
import com.lindroy.androidplayer.logic.network.datasource.NetworkDataSource
import com.lindroy.androidplayer.logic.network.handleException

/**
 * @author Lin
 * @date 2022/1/17
 * @function
 */

private const val TAG = "PagingTag"

sealed class BasePagingSource<E : Any, T : Any>(private val startPageNo: Int = 0) :
    PagingSource<Int, T>() {

    private var pageNo = 0

    private var pageSize = 0

    private var response: ApiResponse<E>? = null

    override fun getRefreshKey(state: PagingState<Int, T>): Int? = null

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> = try {
        //默认从第一页开始加载（下标为 0）
        pageNo = params.key ?: startPageNo
        pageSize = params.loadSize
        response = onLoadResponse(pageNo, pageSize)
        val items = onLoadList(response)
        //上一页的页码
        val preKey = if (pageNo > startPageNo) pageNo - startPageNo else null
        //下一页的页码
        //Todo("没有pageNo参数的接口最好不要使用Paging分页，否则pagesize判断出问题会一直发起请求")
        val nextKey = if (pageSize == Int.MAX_VALUE) null else
            items?.let { if (it.size > pageSize * 2 / 3) pageNo + 1 else null }
        XLog.tag(TAG).d("pageNo = $pageNo，pageSize = $pageSize")
        XLog.tag(TAG).d("size = ${items?.size}")
        if (pageNo == startPageNo && items.isNullOrEmpty()) {
            LoadResult.Error(EmptyDataException())
        } else {
            LoadResult.Page(items!!, preKey, nextKey)
        }
    } catch (e: Exception) {
        if (response != null) {
            LoadResult.Error(handleException(RequestException(response!!)))
        } else {
            LoadResult.Error(e)
        }
    }

    abstract suspend fun onLoadResponse(pageNo: Int, pageSize: Int): ApiResponse<E>?

    abstract fun onLoadList(response: ApiResponse<E>?): List<T>?
}

/**
 * 首页文章列表
 */
class HomeArticlePagingSource : BasePagingSource<PageDataModel<ArticleResp>, ArticleResp>() {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ): ApiResponse<PageDataModel<ArticleResp>> = NetworkDataSource.getHomeArticles(pageNo)

    override fun onLoadList(response: ApiResponse<PageDataModel<ArticleResp>>?) =
        response?.data?.datas
}

/**
 * 知识体系目录
 */
class KnowledgeSystemPagingSource : BasePagingSource<List<KnowledgeResp>, KnowledgeResp>() {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getKnowledgeSystemChapters()

    override fun onLoadList(response: ApiResponse<List<KnowledgeResp>>?) = response?.data
}

/**
 * 项目列表
 */
class ProjectListPagingSource(private val cid: Int) :
    BasePagingSource<PageDataModel<ProjectListResp>, ProjectListResp>(1) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getProjectList(cid, pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<PageDataModel<ProjectListResp>>?) =
        response?.data?.datas
}

/**
 * 公众号文章列表
 */
class WxArticlePagingSource(private val id: Int) :
    BasePagingSource<PageDataModel<WXArticleResp>, WXArticleResp>(1) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getWxArticles(id, pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<PageDataModel<WXArticleResp>>?) =
        response?.data?.datas
}

/**
 * 广场文章列表
 */
class SquareArticlePagingSource : BasePagingSource<PageDataModel<ArticleResp>, ArticleResp>(0) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getSquareArticles(pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<PageDataModel<ArticleResp>>?) =
        response?.data?.datas
}

/**
 * 体系文章列表
 */
class KnowledgeArticlePagingSource(private val cid: Int) :
    BasePagingSource<PageDataModel<ArticleResp>, ArticleResp>(0) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getKnowledgeArticles(cid, pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<PageDataModel<ArticleResp>>?) =
        response?.data?.datas

}

/**
 * 问答
 */
class QuestionListPagingSource : BasePagingSource<PageDataModel<ArticleResp>, ArticleResp>(1) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getQuestionList(pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<PageDataModel<ArticleResp>>?) =
        response?.data?.datas
}

/**
 * 个人积分
 */
class CoinHistoryPagingSource :
    BasePagingSource<PageDataModel<CoinHistoryResp>, CoinHistoryResp>(1) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getCoinHistory(pageNo)

    override fun onLoadList(response: ApiResponse<PageDataModel<CoinHistoryResp>>?) =
        response?.data?.datas
}

/**
 * 积分排行榜
 */
class CoinRankingPagingSource :
    BasePagingSource<PageDataModel<CoinRankingResp>, CoinRankingResp>(1) {
    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getCoinRanking(pageNo)

    override fun onLoadList(response: ApiResponse<PageDataModel<CoinRankingResp>>?) =
        response?.data?.datas
}

/**
 * 我的收藏-文章列表
 */
class CollectedArticlesPagingSource :
    BasePagingSource<PageDataModel<CollectedArticleResp>, CollectedArticleResp>(0) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ): ApiResponse<PageDataModel<CollectedArticleResp>> =
        NetworkDataSource.getCollectedArticles(pageNo)

    override fun onLoadList(response: ApiResponse<PageDataModel<CollectedArticleResp>>?) =
        response?.data?.datas
}

/**
 * 我的分享
 */
class MyShareArticlesPagingSource : BasePagingSource<SharedModel, ArticleResp>(1) {
    override suspend fun onLoadResponse(pageNo: Int, pageSize: Int) =
        NetworkDataSource.getMyShareList(pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<SharedModel>?) =
        response?.data?.shareArticles?.datas
}

/**
 * 搜索结果
 */
class SearchResultPagingSource(private val keyword: String) :
    BasePagingSource<PageDataModel<ArticleResp>, ArticleResp>(0) {

    override suspend fun onLoadResponse(
        pageNo: Int,
        pageSize: Int
    ) = NetworkDataSource.getSearchResult(keyword, pageNo, pageSize)

    override fun onLoadList(response: ApiResponse<PageDataModel<ArticleResp>>?) =
        response?.data?.datas

}